package com.zfk.framework.utils;

import com.zfk.framework.models.CaseData;
import com.zfk.framework.models.ResponseData;
import com.zfk.framework.config.ConfigLoader;
import com.zfk.framework.variable_handling.VariableReplace;
import com.zfk.framework.variable_handling.ResponseExtractor;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import io.restassured.http.ContentType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.util.Map;

/**
 * API 客户端工具类，用于发送 HTTP 请求
 */
public class ApiClient {
    public static final Logger logger = LogManager.getLogger(ApiClient.class);

    //首先处理URL
    public static String buildFullURL(String host, String url) {

        return host + url;
    }

    //然后处理requestType 传参类型

    /**
     * 匹配请求体和传参类型
     *
     * @param request     REST Assured 请求对象
     * @param requestType 请求参数类型
     * @param data        请求参数
     */
    @SuppressWarnings("unchecked")
    private static void setRequestData(RequestSpecification request, String requestType, Object data) {


        switch (requestType.toLowerCase()) {
            case "params":
                if (data instanceof Map) {
                    Map<String, Object> params = VariableReplace.replaceVariablesInMap((Map<String, Object>) data);
                    for (Map.Entry<String, Object> entry : params.entrySet()) {
                        request.queryParam(entry.getKey(), entry.getValue().toString());
                    }
                }
                break;
            case "form":
                if (data instanceof Map) {
                    Map<String, Object> formData = VariableReplace.replaceVariablesInMap((Map<String, Object>) data);
                    // 优先使用 application/x-www-form-urlencoded，简单表单上传
                    request.contentType(ContentType.URLENC);
                    for (Map.Entry<String, Object> entry : formData.entrySet()) {
                        request.formParam(entry.getKey(), entry.getValue().toString());
                    }
                }
                break;
            case "json":
                if (data instanceof Map) {
                    Map<String, Object> jsonData = VariableReplace.replaceVariablesInMap((Map<String, Object>) data);
                    request.contentType(ContentType.JSON).body(jsonData);
                } else if (data instanceof String) {
                    String jsonBody = VariableReplace.replaceVariables((String) data);
                    request.contentType(ContentType.JSON).body(jsonBody);
                }
                break;
            case "file"://这部分需要根据上传文件的方案调整，这里不做穷举
                if (data instanceof Map) {
                    Map<String, Object> fileData = VariableReplace.replaceVariablesInMap((Map<String, Object>) data);
                    request.contentType(ContentType.MULTIPART);
                    boolean hasFile = false;
                    for (Map.Entry<String, Object> entry : fileData.entrySet()) {
                        String value = entry.getValue().toString();
                        File file = new File(value);
                        if (file.exists()) {
                            request.multiPart(entry.getKey(), file);
                            hasFile = true;
                        } else {
                            // 非文件字段作为普通 multipart 参数
                            request.multiPart(entry.getKey(), value);
                        }
                    }
                    if (!hasFile) {
                        logger.error("文件不存在，请检查文件路径");
                        throw new RuntimeException("上传文件需要指定文件路径'");
                    }
                }
                break;
            default:
                throw new IllegalArgumentException("不支持的请求传参方式: " + requestType);
        }
    }

    /**
     * 发送 HTTP 请求
     *
     * @param caseID   用例ID
     * @param caseData 用例数据
     * @return 响应结果数据
     */
    public static ResponseData sendRequest(String caseID, CaseData caseData) {
        //组织发送请求所需的参数

        // 获取 host 并拼接 URL
        String host = ConfigLoader.getConfig().getHost();
        String rawUrl = caseData.getUrl();
        String fullUrl = buildFullURL(host, rawUrl);

        //处理url路径传参的情况
        String url = VariableReplace.replaceVariables(fullUrl);

        //请求方式
        String method = caseData.getMethod().toUpperCase();

        //传参方式
        String requestType = caseData.getRequestType();

        //请求头
        Map<String, Object> headers = caseData.getHeaders();

        //请求参数
        Object data = caseData.getData();

//        logger.info("Sending {} request to: {}, requestType: {}", method, url, requestType);

        try {
            // 创建 REST Assured 请求，关闭 SSL 证书验证
            RequestSpecification request = RestAssured.given().relaxedHTTPSValidation();

            // 设置请求头
            if (headers != null) {
                Map<String, Object> replacedHeaders = VariableReplace.replaceVariablesInMap(headers);
                for (Map.Entry<String, Object> header : replacedHeaders.entrySet()) {
                    request.header(header.getKey(), header.getValue().toString());
                }
            }

            // 设置请求体或查询参数
            if (data != null || "params".equalsIgnoreCase(requestType)) {
                setRequestData(request, requestType, data);
            }

            // 发送请求 使用增强的switch表达式
            Response response = switch (method) {
                case "GET" -> request.get(url);
                case "POST" -> request.post(url);
                case "PATCH" -> request.patch(url);
                case "DELETE" -> request.delete(url);
                case "HEAD" -> request.head(url);
                case "OPTIONS" -> request.options(url);
                default -> throw new IllegalArgumentException("不支持的请求方式" + method);
            };

            // 获取响应时间（毫秒）
            long duration = response.time();

            String responseBody = response.asString();
            int statusCode = response.getStatusCode();
            //如果断言需要处理headers
            String headersString = response.getHeaders().toString();
            
            logger.info("接收到用例 {}的响应{}，耗时{}毫秒", caseID, responseBody, duration);

            // 提取响应变量
            if (caseData.getExtract() != null) {
                ResponseExtractor.extractVariables(responseBody, caseData.getExtract());
            }

            return new ResponseData(responseBody, statusCode, duration,headersString);
        } catch (Exception e) {
            logger.error("用例 {} 发送 {} 请求到 {}失败 {}",
                    caseID,method, url,  e.getMessage());
            throw new RuntimeException("请求发送失败 " + caseID, e);
        }
    }

}